setClass("BootstrapFramework",
		representation(
				.description="character",
				.bootstraper="VBootstrapedSet",
				.scoreObj="VScore",
				.finalResultProducer="VBFrameworkFinalResult",
				.listComp="list"#"VListComputer"
		),
		prototype=prototype(
				.description="BootstrapFramework class"
		),
		validity=function(.Object){
			#Check .scoreObj class
			listObjClass <-NULL
			if(is(.Object@.scoreObj,"ClusterScore")){
				listObjClass <-"ReduceClustListComputer"
			}
			else if(is(.Object@.scoreObj,"ReductionScore")){
				listObjClass <- "ReduceListComputer"
			}
			listLen <-length(.Object@.listComp)
			
			
			isClassVec <-unlist( lapply(1:listLen,FUN=function(n,li){
								is(li[[n]],listObjClass)
							},.Object@.listComp) )
			if(sum(isClassVec) < listLen){
				stop("some of listComp objects have wrong class")
			}
			
		}
)   
#generic functions
setGeneric("computeDistributions",function(.Object,...){standardGeneric("computeDistributions")})
setGeneric("runFramework",function(.Object,...){standardGeneric("runFramework")})

#methods

setMethod("initialize",
		signature="BootstrapFramework",
		function(.Object,bootstraper,scoreObj,finalResultProducer,listComp,...){
			.Object@.bootstraper <- bootstraper
			.Object@.scoreObj <- scoreObj
			.Object@.finalResultProducer <- finalResultProducer
			.Object@.listComp <- listComp
			registerDoMC(cores=6)
			
			validObject(.Object)
			return(.Object)
		})

setMethod("computeDistributions",
		signature="BootstrapFramework",
		definition=function(.Object,...){
			#TODO implement
			bootstrapedSetsNumber <- getSamplesNumber(.Object@.bootstraper)
			listLen <-length(.Object@.listComp)
			#matrix contains initial distributions
			preOutMatrix <- matrix( rep( 0,listLen*bootstrapedSetsNumber ),nrow=listLen )
#			print("PO matrix:");print(dim(preOutMatrix))
			print("Number of computers: ");print(listLen)
			#compute over all bootstraped sets
			bootstrapedSet <-NULL
			for(setNr in 1:bootstrapedSetsNumber){
				print("NewBootstrapedSet")
				bootstrapedSet <- getAt(.Object@.bootstraper, setNr)#this is List set
				
				#clean list computers
				for(i in 1:listLen){
					cleanSavedSet(.Object@.listComp[[i]])
				}
				
				#matrixColumn <-unlist( foreach( n=seq( from=1, to=listLen, by=1 )) %do%{
				matrixColumn <-unlist( lapply(1:listLen,FUN=function(n){
								print(paste("At: ",n));
									#on each list element perform algorithms and score the
									computed <-computeList(.Object@.listComp[[n]],bootstrapedSet)
									#print("before score")
									scored <-ScoreSet(.Object@.scoreObj,computed,computed$clusters)
									#protection against numerical error
									if(is.na(scored) || is.infinite(scored)){scored <- -.Machine$double.xmax}
									#print("END: ");print(n)
									return(scored)
								} ))
#				print("MatrixColumn len: ");print(length(matrixColumn))
#				print("MA: ");print(matrixColumn)
				
				preOutMatrix[,setNr] <- matrixColumn
				
			}
			
			#compute final output List
			#add description to each row
			outList <- lapply(1:listLen,FUN=function(n,clist,outMatrix){
						tmpMatrix <- preOutMatrix[n,,drop=FALSE]
						rownames(tmpMatrix) <- get_description(clist[[n]])
						return(tmpMatrix)
					},.Object@.listComp,preOutMatrix)
			return(outList)
		}
)

setMethod("runFramework",
		signature="BootstrapFramework",
		definition=function(.Object,...){
			distributionsList <- computeDistributions(.Object)
			finalResult <- computeBFResult(.Object@.finalResultProducer,distributionsList)
			#clean list computers
			listLen <-length(.Object@.listComp) 
			for(i in 1:listLen){
				cleanSavedSet(.Object@.listComp[[i]])
			}
			return(finalResult)
		}
)

setMethod("get_description",
		signature="VListComputer",
		definition=function(.Object){
			.Object@.description
		})

